﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.Revit;
using YJKGeometryFuncs;
using YJKRevitStairs.StairsModel.CommonUnit;
using YJKRevitStairs.StairsModel.DataInfos;

namespace YJKRevitStairs.StairsModel.Manage
{
	public class StairsCreator
	{
		public StairsCreator(ExternalCommandData commandData)
		{
			this.m_Revit = commandData;
			this.m_Document = this.m_Revit.Application.ActiveUIDocument.Document;
			this.m_RevitVersion = this.m_Revit.Application.Application.VersionNumber;
		}

		protected bool ChangeStairsRunType(StairsType stairsType, RunInfo runInfo)
		{
			ElementId runType = stairsType.RunType;
			StairsRunType stairsRunType = this.m_Document.GetElement(runType) as StairsRunType;
			string text = stairsType.Name + " " + Common.FeetToMM(runInfo.RunStructalDepth).ToString("f0") + "mm 结构深度";
			StairsRunType stairsRunType2 = null;
			if (!ComponentTypeManager.GetStairsRunType(this.m_Document, text, ref stairsRunType2))
			{
				stairsRunType2 = (stairsRunType.Duplicate(text) as StairsRunType);
				stairsRunType2.get_Parameter(BuiltInParameter.STAIRS_RUNTYPE_STRUCTURAL_DEPTH).Set(runInfo.RunStructalDepth);
				stairsRunType2.GetParameter(BuiltInParameter.STAIRS_TRISERTYPE_TREAD).Set(1);
				stairsRunType2.GetParameter(BuiltInParameter.STAIRS_TRISERTYPE_TREAD_THICKNESS).Set(runInfo.TreadThickness);
				stairsRunType2.GetParameter(BuiltInParameter.STAIRS_TRISERTYPE_RISER).Set(1);
				stairsRunType2.GetParameter(BuiltInParameter.STAIRS_TRISERTYPE_RISER_THICKNESS).Set(runInfo.RiserThickness);
				ElementId materialIdByName = Common.GetMaterialIdByName(this.m_Document, "钢筋混凝土");
				Parameter parameter = stairsRunType2.get_Parameter(BuiltInParameter.STAIRS_RUNTYPE_RUN_MATERIAL);
				if (parameter != null && !parameter.IsReadOnly && materialIdByName != null)
				{
					parameter.Set(materialIdByName);
				}
				materialIdByName = Common.GetMaterialIdByName(this.m_Document, "水泥砂浆");
				parameter = stairsRunType2.get_Parameter(BuiltInParameter.STAIRS_TRISERTYPE_TREAD_MATERIAL);
				if (parameter != null && !parameter.IsReadOnly && materialIdByName != null)
				{
					parameter.Set(materialIdByName);
				}
				parameter = stairsRunType2.get_Parameter(BuiltInParameter.STAIRS_TRISERTYPE_RISER_MATERIAL);
				if (parameter != null && !parameter.IsReadOnly && materialIdByName != null)
				{
					parameter.Set(materialIdByName);
				}
			}
			if (stairsRunType2 != null && stairsType != null)
			{
				stairsType.get_Parameter(BuiltInParameter.STAIRSTYPE_RUN_TYPE).Set(stairsRunType2.Id);
			}
			return true;
		}

		protected bool ChangeLandingType(StairsType stairsType, double dLandingThick)
		{
			ElementId landingType = stairsType.LandingType;
			StairsLandingType stairsLandingType = this.m_Document.GetElement(landingType) as StairsLandingType;
			string text = stairsType.Name + " " + Common.FeetToMM(dLandingThick).ToString("f0") + "mm平台厚度";
			StairsLandingType stairsLandingType2 = null;
			if (!ComponentTypeManager.GetStarisLandingType(this.m_Document, text, ref stairsLandingType2))
			{
				stairsLandingType2 = (stairsLandingType.Duplicate(text) as StairsLandingType);
				stairsLandingType2.GetParameter(BuiltInParameter.STAIRS_LANDINGTYPE_THICKNESS).Set(dLandingThick);
				ElementId materialIdByName = Common.GetMaterialIdByName(this.m_Document, "钢筋混凝土");
				Parameter parameter = stairsLandingType2.get_Parameter(BuiltInParameter.STAIRS_LANDINGTYPE_LANDING_MATERIAL);
				if (parameter != null && !parameter.IsReadOnly && materialIdByName != null)
				{
					parameter.Set(materialIdByName);
				}
			}
			if (stairsLandingType2 != null && stairsType != null)
			{
				stairsType.GetParameter(BuiltInParameter.STAIRSTYPE_LANDING_TYPE).Set(stairsLandingType2.Id);
			}
			return true;
		}

		protected bool GetLevel(double bottomElevation, double topElevation, ref ElementId bottomLevelId, ref ElementId topLevelId, ref double bottomOffset, ref double topOffset, double dTopHeight, ref ElementId delLevelId)
		{
			List<Level> sortLevels = Common.GetSortLevels(this.m_Document, double.MinValue, double.MaxValue);
			double num = double.MaxValue;
			double num2 = double.MaxValue;
			int i = 0;
			int num3 = -1;
			int num4 = -1;
			while (i < sortLevels.Count)
			{
				Level level = sortLevels[i];
				double num5 = bottomElevation - level.Elevation;
				if (YJKRevitStairs.StairsModel.CommonUnit.Geometry.LessThan(Math.Abs(num5), Math.Abs(num)))
				{
					num3 = i;
					num = num5;
				}
				double num6 = topElevation - level.Elevation;
				if (YJKRevitStairs.StairsModel.CommonUnit.Geometry.LessThan(Math.Abs(num6), Math.Abs(num2)))
				{
					num4 = i;
					num2 = num6;
				}
				i++;
			}
			if (num3 == -1)
			{
				YJKMessageBox.Show("无法匹配到当前的底标高，请先添加相应的楼层标高");
				return false;
			}
			if (!YJKGeometryFuncs.Geometry.IsEqual(num, 0.0) && num3 != 0)
			{
				bottomLevelId = sortLevels[num3 - 1].Id;
				Level level2 = this.m_Document.GetElement(bottomLevelId) as Level;
				bottomOffset = bottomElevation - level2.Elevation;
			}
			else
			{
				bottomLevelId = sortLevels[num3].Id;
				bottomOffset = num;
			}
			if (num4 != -1)
			{
				if (num4 != num3)
				{
					topLevelId = sortLevels[num4].Id;
					topOffset = num2;
				}
				else if (num4 != sortLevels.Count - 1)
				{
					topLevelId = sortLevels[num4 + 1].Id;
					topOffset = topElevation - sortLevels[num4 + 1].Elevation;
				}
				else if (YJKGeometryFuncs.Geometry.IsEqual(num2, 0.0))
				{
					topLevelId = sortLevels[num4].Id;
					topOffset = num2;
				}
				else
				{
					int index = sortLevels.Count - 1;
					if (this.m_Document.GetElement(sortLevels[index].Id) is Level)
					{
						Level level3 = this.NewLevel(topElevation);
						if (level3 != null)
						{
							delLevelId = level3.Id;
							topLevelId = delLevelId;
						}
					}
				}
				return true;
			}
			YJKMessageBox.Show("无法匹配到当前的顶标高，请先添加相应的楼层标高");
			return false;
		}

		protected Level NewLevel(double elevation)
		{
			Level level = null;
			using (Transaction transaction = new Transaction(this.m_Document, "Create a new level"))
			{
				transaction.Start();
				level = this.m_Document.HyNewLevel(elevation);
				if (level == null)
				{
					transaction.RollBack();
					throw new Exception("Create a new level failed.");
				}
				transaction.Commit();
			}
			return level;
		}

		protected void DelLevel(ElementId LevelId)
		{
			using (Transaction transaction = new Transaction(this.m_Document, "Delete level"))
			{
				transaction.Start();
				try
				{
					if (LevelId != null)
					{
						this.m_Document.Delete(LevelId);
					}
				}
				catch (Exception)
				{
					transaction.RollBack();
				}
				transaction.Commit();
			}
		}

		protected bool StairsLevelIsValid(ElementId bottomId, ElementId topId)
		{
			bool result = false;
			if (bottomId == null || topId == null)
			{
				return result;
			}
			double num = 0.0;
			double num2 = 0.0;
			Level level = this.m_Document.GetElement(bottomId) as Level;
			if (level != null)
			{
				num = level.Elevation;
			}
			Level level2 = this.m_Document.GetElement(topId) as Level;
			if (level2 != null)
			{
				num2 = level2.Elevation;
			}
			if (num2 > num)
			{
				result = true;
			}
			return result;
		}

		protected bool ChangeStairsType(Stairs stairs, StairsType stairsType, RunInfo runInfo, string stairsName, double dLandingThick = 0.0)
		{
			try
			{
				if (stairsType == null)
				{
					return false;
				}
				string text = stairsName + "-" + ComponentTypeManager.GetYJKStairsTypeNumber(this.m_Document).ToString();
				StairsType stairsType2 = stairsType.Duplicate(text) as StairsType;
				this.ChangeStairsRunType(stairsType2, runInfo);
				if (dLandingThick > 1E-09)
				{
					this.ChangeLandingType(stairsType2, dLandingThick);
				}
				stairsType2.MinRunWidth = runInfo.RunWidth;
				stairsType2.MinTreadDepth = runInfo.TreadDepth;
				stairsType2.MaxRiserHeight = runInfo.TreadHeight;
				stairs.ChangeTypeId(stairsType2.Id);
				stairs.ActualTreadDepth = runInfo.TreadDepth;
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private Face getRectangleSolidTopFace(Solid solid)
		{
			Face result = null;
			if (solid != null)
			{
				foreach (object obj in solid.Faces)
				{
					Face face = (Face)obj;
					if (face.ComputeNormal(UV.Zero).Z < 0.0)
					{
						result = face;
						break;
					}
				}
			}
			return result;
		}

		private SortedDictionary<double, List<Edge>> GetFaceLengthDictionary(Face validFace)
		{
			SortedDictionary<double, List<Edge>> sortedDictionary = new SortedDictionary<double, List<Edge>>();
			foreach (object obj in validFace.EdgeLoops)
			{
				foreach (object obj2 in ((EdgeArray)obj))
				{
					Edge edge = (Edge)obj2;
					double num = edge.ApproximateLength;
					num = Math.Round(num, 3);
					if (!sortedDictionary.ContainsKey(num))
					{
						sortedDictionary.Add(num, new List<Edge>
						{
							edge
						});
					}
					else
					{
						sortedDictionary[num].Add(edge);
					}
				}
			}
			return sortedDictionary;
		}

		private List<XYZ> GetSupportTopMidProjectionPoints(ElementId supportId)
		{
			List<XYZ> list = new List<XYZ>();
			Element element = this.m_Document.GetElement(supportId);
			Options options = new Options();
			foreach (GeometryObject geometryObject in element.get_Geometry(options))
			{
				Solid solid = geometryObject as Solid;
				if (null != solid)
				{
					Face rectangleSolidTopFace = this.getRectangleSolidTopFace(solid);
					if (rectangleSolidTopFace != null)
					{
						SortedDictionary<double, List<Edge>> faceLengthDictionary = this.GetFaceLengthDictionary(rectangleSolidTopFace);
						if (faceLengthDictionary.Count > 0)
						{
							foreach (KeyValuePair<double, List<Edge>> keyValuePair in faceLengthDictionary)
							{
								foreach (Edge edge in keyValuePair.Value)
								{
									Curve curve = edge.AsCurve();
									if (curve != null)
									{
										XYZ item = (curve.GetEndPoint(0) + curve.GetEndPoint(1)) / 2.0;
										list.Add(item);
									}
								}
								if (list.Count == 2)
								{
									break;
								}
							}
						}
					}
				}
			}
			return list;
		}

		protected List<ElementId> GetStairsOutsupportIds(Stairs stairs, List<XYZ> arOutSupportPt, double dSupportWidth)
		{
			List<ElementId> list = new List<ElementId>();
			if (arOutSupportPt.Count == 0)
			{
				return list;
			}
			foreach (ElementId elementId in stairs.GetStairsSupports())
			{
				foreach (XYZ xyz in this.GetSupportTopMidProjectionPoints(elementId))
				{
					XYZ xyz2 = new XYZ(xyz.X, xyz.Y, 0.0);
					foreach (XYZ xyz3 in arOutSupportPt)
					{
						XYZ xyz4 = new XYZ(xyz3.X, xyz3.Y, 0.0);
						if (xyz2.DistanceTo(xyz4) - dSupportWidth < 0.8 && !list.Contains(elementId))
						{
							list.Add(elementId);
						}
					}
				}
			}
			return list;
		}

		protected double GetSupportTypeWidth(Autodesk.Revit.DB.ElementType supportType)
		{
			Common.MMToFeet(50.0);
			return supportType.get_Parameter(BuiltInParameter.STAIRS_SUPPORTTYPE_WIDTH).AsDouble();
		}

		private bool HasSupportStyle(List<BaseSupportData> ListSupport, SupportStyle style)
		{
			bool result = false;
			using (List<BaseSupportData>.Enumerator enumerator = ListSupport.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					if (enumerator.Current.Style == style)
					{
						result = true;
						break;
					}
				}
			}
			return result;
		}

		private Autodesk.Revit.DB.ElementType GetSupportType(List<BaseSupportData> ListSupport)
		{
			Autodesk.Revit.DB.ElementType result = null;
			using (List<BaseSupportData>.Enumerator enumerator = ListSupport.GetEnumerator())
			{
				if (enumerator.MoveNext())
				{
					result = enumerator.Current.SupportType;
				}
			}
			return result;
		}

		protected bool ChangeSupportType(Stairs stairs, List<BaseSupportData> ListSupport, List<ElementId> arOutSupportId)
		{
			using (Transaction transaction = new Transaction(this.m_Document, "change support type"))
			{
				transaction.Start();
				try
				{
					ICollection<ElementId> stairsSupports = stairs.GetStairsSupports();
					if (ListSupport.Count == 0)
					{
						IEnumerator<ElementId> enumerator = stairsSupports.GetEnumerator();
						{
							while (enumerator.MoveNext())
							{
								ElementId elementId = enumerator.Current;
								this.m_Document.Delete(elementId);
							}
							goto IL_1A5;
						}
					}
					Autodesk.Revit.DB.ElementType supportType = this.GetSupportType(ListSupport);
					ElementId typeId = stairs.GetTypeId();
					StairsType stairsType = this.m_Document.GetElement(typeId) as StairsType;
					if (supportType != null)
					{
						if (supportType.Name.Contains("梯边"))
						{
							stairsType.get_Parameter(BuiltInParameter.STAIRSTYPE_HAS_RIGHT_SUPPORT).Set(1);
							stairsType.get_Parameter(BuiltInParameter.STAIRSTYPE_HAS_LEFT_SUPPORT).Set(1);
						}
						else
						{
							stairsType.get_Parameter(BuiltInParameter.STAIRSTYPE_HAS_RIGHT_SUPPORT).Set(2);
							stairsType.get_Parameter(BuiltInParameter.STAIRSTYPE_HAS_LEFT_SUPPORT).Set(2);
						}
						if (!this.HasSupportStyle(ListSupport, SupportStyle.ST_Inside))
						{
							foreach (ElementId elementId2 in stairsSupports)
							{
								if (!arOutSupportId.Contains(elementId2))
								{
									this.m_Document.Delete(elementId2);
								}
							}
						}
						if (!this.HasSupportStyle(ListSupport, SupportStyle.ST_OutSide))
						{
							foreach (ElementId elementId3 in arOutSupportId)
							{
								this.m_Document.Delete(elementId3);
							}
						}
						if (!this.HasSupportStyle(ListSupport, SupportStyle.ST_Mid))
						{
							stairsType.get_Parameter(BuiltInParameter.STAIRSTYPE_HAS_INTERMEDIATE_SUPPORT).Set(0);
						}
						else
						{
							stairsType.get_Parameter(BuiltInParameter.STAIRSTYPE_HAS_INTERMEDIATE_SUPPORT).Set(0);
						}
					}
					IL_1A5:
					transaction.Commit();
				}
				catch (Exception)
				{
					transaction.RollBack();
				}
			}
			return true;
		}

		protected bool SetDefaultSurpportType(Stairs stairs, List<BaseSupportData> ListSupport)
		{
			bool result = false;
			using (Transaction transaction = new Transaction(this.m_Document, "SetType"))
			{
				transaction.Start();
				try
				{
					Autodesk.Revit.DB.ElementType supportType = this.GetSupportType(ListSupport);
					ElementId typeId = stairs.GetTypeId();
					StairsType stairsType = this.m_Document.GetElement(typeId) as StairsType;
					if (supportType != null)
					{
						if (supportType.Name.Contains("梯边"))
						{
							stairsType.get_Parameter(BuiltInParameter.STAIRSTYPE_HAS_RIGHT_SUPPORT).Set(1);
							stairsType.get_Parameter(BuiltInParameter.STAIRSTYPE_HAS_LEFT_SUPPORT).Set(1);
						}
						else
						{
							stairsType.get_Parameter(BuiltInParameter.STAIRSTYPE_HAS_RIGHT_SUPPORT).Set(2);
							stairsType.get_Parameter(BuiltInParameter.STAIRSTYPE_HAS_LEFT_SUPPORT).Set(2);
						}
						result = true;
					}
					transaction.Commit();
				}
				catch (Exception)
				{
					transaction.RollBack();
					result = false;
				}
			}
			return result;
		}

		private bool PointOnRailPath(Railing rail, XYZ pt)
		{
			bool result = false;
			if (rail != null)
			{
				XYZ xyz = new XYZ(pt.X, pt.Y, 0.0);
				foreach (Curve curve in (rail.GetPath() as List<Curve>))
				{
					XYZ endPoint = curve.GetEndPoint(0);
					XYZ xyz2 = new XYZ(endPoint.X, endPoint.Y, 0.0);
					endPoint = curve.GetEndPoint(1);
					XYZ xyz3 = new XYZ(endPoint.X, endPoint.Y, 0.0);
					double num = xyz2.DistanceTo(xyz);
					double num2 = xyz3.DistanceTo(xyz);
					if (num < 0.5 || num2 < 0.5)
					{
						result = true;
						break;
					}
				}
			}
			return result;
		}

		protected void DeleteStairsTopLandRailing(Stairs stairs)
		{
			if (stairs != null)
			{
				Transaction transaction = new Transaction(this.m_Document, "delete rail");
				transaction.Start();
				try
				{
					IEnumerable<ElementId> associatedRailings = stairs.GetAssociatedRailings();
					new SortedDictionary<double, ElementId>();
					foreach (ElementId elementId in associatedRailings)
					{
						IList<Curve> path = (this.m_Document.GetElement(elementId) as Railing).GetPath();
						int count = path.Count;
						Curve curve = path[0];
						Curve curve2 = path[count - 1];
						if (curve.GetEndPoint(0).IsAlmostEqualTo(curve2.GetEndPoint(1)))
						{
							this.m_Document.Delete(elementId);
						}
					}
					transaction.Commit();
				}
				catch (Exception)
				{
					transaction.RollBack();
				}
			}
		}

		private Dictionary<ElementId, BaseRaillingData> getRailingIdByStartPoint(Stairs stairs, List<BaseRaillingData> rails)
		{
			Dictionary<ElementId, BaseRaillingData> dictionary = new Dictionary<ElementId, BaseRaillingData>();
			foreach (BaseRaillingData baseRaillingData in rails)
			{
				XYZ ptStart = baseRaillingData.m_ptStart;
				foreach (ElementId elementId in stairs.GetAssociatedRailings())
				{
					Railing rail = this.m_Revit.Application.ActiveUIDocument.Document.GetElement(elementId) as Railing;
					if (this.PointOnRailPath(rail, ptStart) && !dictionary.ContainsKey(elementId))
					{
						dictionary.Add(elementId, baseRaillingData);
					}
				}
			}
			return dictionary;
		}

		protected bool ChangeRailingType(Stairs stairs, List<BaseRaillingData> arRailings)
		{
			using (Transaction transaction = new Transaction(this.m_Document, "change type"))
			{
				transaction.Start();
				try
				{
					Dictionary<ElementId, BaseRaillingData> railingIdByStartPoint = this.getRailingIdByStartPoint(stairs, arRailings);
					IEnumerable<ElementId> associatedRailings = stairs.GetAssociatedRailings();
					int num = 0;
					foreach (ElementId elementId in associatedRailings)
					{
						if (!railingIdByStartPoint.ContainsKey(elementId))
						{
							this.m_Document.Delete(elementId);
							num++;
						}
						else
						{
							BaseRaillingData baseRaillingData = railingIdByStartPoint[elementId];
							if (baseRaillingData.TheRailingType != null)
							{
								(this.m_Revit.Application.ActiveUIDocument.Document.GetElement(elementId) as Railing).ChangeTypeId(baseRaillingData.TheRailingType.Id);
								num++;
							}
						}
					}
					transaction.Commit();
				}
				catch (Exception ex)
				{
					TaskDialog.Show("error", ex.Message);
					transaction.RollBack();
				}
			}
			return true;
		}

        public void SetStairsCutMarkType(Stairs stairs, YJKRevitStairs.StairsModel.DataInfos.FloorType floorType)
		{
            if (floorType != YJKRevitStairs.StairsModel.DataInfos.FloorType.FT_Top)
			{
				return;
			}
			Transaction transaction = new Transaction(this.m_Document, "cutmarktype");
			transaction.Start();
			try
			{
				ElementId typeId = stairs.GetTypeId();
				StairsType stairsType = this.m_Document.GetElement(typeId) as StairsType;
				if (stairsType != null)
				{
					Parameter parameter = stairsType.get_Parameter(BuiltInParameter.STAIRSTYPE_CUTMARK_TYPE);
					if (parameter != null)
					{
						ElementId elementId = parameter.AsElementId();
						CutMarkType cutMarkType = this.m_Document.GetElement(elementId) as CutMarkType;
						if (cutMarkType != null)
						{
							CutMarkType cutMarkTypeByName = ComponentTypeManager.GetCutMarkTypeByName(this.m_Document, cutMarkType, "单锯齿线StairsTop");
							if (cutMarkTypeByName != null)
							{
								parameter.Set(cutMarkTypeByName.Id);
							}
						}
					}
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

        public void SetStairsBottomFloorVisibility(Stairs stairs, YJKRevitStairs.StairsModel.DataInfos.FloorType floorType, Autodesk.Revit.DB.View view, List<BuiltInCategory> arBuiltInCategory)
		{
			if (!stairs.IsValidObject)
			{
				return;
			}
			bool bVisible = false;
            if (floorType != YJKRevitStairs.StairsModel.DataInfos.FloorType.FT_Bottom)
			{
				bVisible = true;
			}
			this.SetSubCategoryVisibility(view, bVisible, stairs.Category, arBuiltInCategory);
			this.SetSubCategorySolidLinePattern(view, floorType, stairs.Category, arBuiltInCategory);
			ICollection<ElementId> associatedRailings = stairs.GetAssociatedRailings();
			if (associatedRailings.Count > 0)
			{
				ElementId elementId = associatedRailings.First<ElementId>();
				Element element = this.m_Document.GetElement(elementId);
				this.SetSubCategoryVisibility(view, bVisible, element.Category, arBuiltInCategory);
			}
			this.SetStairsCutMarkType(stairs, floorType);
		}

		protected List<BuiltInCategory> CreateStairBottomVisibleBuiltInCate()
		{
			return new List<BuiltInCategory>
			{
				(BuiltInCategory)(-2000931),
				(BuiltInCategory)(-2000933),
				(BuiltInCategory)(-2000935),
				(BuiltInCategory)(-2000937),
				(BuiltInCategory)(-2000124),
				(BuiltInCategory)(-2000950),
				(BuiltInCategory)(-2000951),
				(BuiltInCategory)(-2000132)
			};
		}

		private void SetSubCategoryVisibility(Autodesk.Revit.DB.View view, bool bVisible, Category category, List<BuiltInCategory> arBuiltInCategory)
		{
			Transaction transaction = new Transaction(this.m_Document, "visible");
			transaction.Start();
			try
			{
				CategoryNameMap subCategories = category.SubCategories;
				foreach (BuiltInCategory builtInCategory in arBuiltInCategory)
				{
					foreach (object obj in subCategories)
					{
						Category category2 = (Category)obj;
                        if ((int)builtInCategory == category2.Id.IntegerValue)
						{
							view.SetYJKVisibility(category2, bVisible);
							break;
						}
					}
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

        private void SetSubCategorySolidLinePattern(Autodesk.Revit.DB.View view, YJKRevitStairs.StairsModel.DataInfos.FloorType floorType, Category category, List<BuiltInCategory> arBuiltInCategory)
		{
			Transaction transaction = new Transaction(this.m_Document, "line pattern");
			transaction.Start();
			try
			{
				CategoryNameMap subCategories = category.SubCategories;
                if (floorType == YJKRevitStairs.StairsModel.DataInfos.FloorType.FT_Mid || floorType == YJKRevitStairs.StairsModel.DataInfos.FloorType.FT_Top)
				{
					ElementId solidPatternId = LinePatternElement.GetSolidPatternId();
					OverrideGraphicSettings overrideGraphicSettings = new OverrideGraphicSettings();
					overrideGraphicSettings.SetProjectionLinePatternId(solidPatternId);
					foreach (BuiltInCategory builtInCategory in arBuiltInCategory)
					{
						foreach (object obj in subCategories)
						{
							Category category2 = (Category)obj;
                            if ((int)builtInCategory == category2.Id.IntegerValue)
							{
								view.SetCategoryOverrides(category2.Id, overrideGraphicSettings);
								break;
							}
						}
					}
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		protected void SetBeamElevation(ref List<BeamCurveInfo> arBeamCurve, BeamType type, int nFloorNum, double dElevation)
		{
			foreach (BeamCurveInfo beamCurveInfo in arBeamCurve)
			{
				if (beamCurveInfo.m_Type == type && beamCurveInfo.m_nFloorNum == nFloorNum)
				{
					beamCurveInfo.m_BottomElevation = dElevation;
				}
			}
		}

		protected void SetBottomBeamRealLocation(ref List<BeamCurveInfo> lstBeamCurve, StairsRunManager runManger, double dBeamWidth = 0.0)
		{
			double dTrans = runManger.GetStairsRunRiserThickness() + dBeamWidth;
			this.SetBeamRealLocation(ref lstBeamCurve, dTrans, BeamType.BT_Bottom);
		}

		protected void SetTopBeamRealLocation(ref List<BeamCurveInfo> lstBeamCurve, StairsRunManager runManger, double dBeamWidth = 0.0)
		{
			double dTrans = runManger.GetStairsRunRiserThickness() + dBeamWidth;
			this.SetBeamRealLocation(ref lstBeamCurve, dTrans, BeamType.BT_Top);
		}

		public void SetBeamRealLocation(ref List<BeamCurveInfo> lstBeamCurve, double dTrans, BeamType beamType)
		{
			foreach (BeamCurveInfo beamCurveInfo in lstBeamCurve)
			{
				if (beamCurveInfo.m_Type == beamType)
				{
					List<CurveInfo> list = new List<CurveInfo>();
					for (int i = 0; i < beamCurveInfo.m_arCurveInfo.Count; i++)
					{
						CurveInfo item = beamCurveInfo.m_arCurveInfo.ElementAt(i);
						if (item.Normal == null)
						{
							list.Add(item);
						}
						else
						{
							Transform transform = Transform.CreateTranslation(item.Normal.Multiply(dTrans));
							item.CurveObj = item.CurveObj.CreateTransformed(transform);
							list.Add(item);
						}
					}
					if (list.Count > 0)
					{
						beamCurveInfo.m_arCurveInfo.Clear();
						beamCurveInfo.m_arCurveInfo.AddRange(list);
					}
				}
			}
		}

		protected void ShowStairsPath(ElementId stairsId, bool bShow)
		{
			if (!bShow && stairsId != null)
			{
				Transaction transaction = new Transaction(this.m_Document, "New Stairs Path");
				transaction.Start();
				try
				{
					foreach (ElementId elementId in new FilteredElementCollector(this.m_Document).OfClass(typeof(StairsPath)).ToElementIds())
					{
						StairsPath stairsPath = this.m_Document.GetElement(elementId) as StairsPath;
						if (stairsPath != null && stairsPath.StairsId.HostElementId.Equals(stairsId))
						{
							this.m_Document.Delete(elementId);
						}
					}
					transaction.Commit();
				}
				catch (Exception)
				{
					transaction.RollBack();
				}
			}
		}

		protected void WriteStairsLandWidthXData(Stairs stairs, string sSchemaName, string sFieldName, List<string> arStrValue)
		{
			ElementXDataManager.CreateStairsXDataSchema(stairs, sSchemaName, new List<string>
			{
				ElementXDataManager.m_sStairsLand,
				ElementXDataManager.m_sStairsBeam
			}, new List<Type>
			{
				typeof(string),
				typeof(ElementId)
			});
			ElementXDataManager.WriteStairsLandWidthXData(stairs, sFieldName, arStrValue);
		}

		protected bool IsStairsValid(ElementId starisId)
		{
			bool result = true;
			if (starisId == null)
			{
				return false;
			}
			if (!(this.m_Document.GetElement(starisId) is Stairs))
			{
				result = false;
			}
			return result;
		}

		protected void TranslationStairs(Stairs stairs, XYZ vecTrans, XYZ ptInsert, double bottomOffset, double topOffset)
		{
			ElementTransformUtils.MoveElement(this.m_Document, stairs.Id, vecTrans);
			if (!YJKRevitStairs.StairsModel.CommonUnit.Geometry.IsEqual(bottomOffset, 0.0))
			{
				stairs.get_Parameter(BuiltInParameter.STAIRS_BASE_OFFSET).Set(bottomOffset);
			}
			if (!YJKRevitStairs.StairsModel.CommonUnit.Geometry.IsEqual(topOffset, 0.0))
			{
				stairs.get_Parameter(BuiltInParameter.STAIRS_TOP_OFFSET).Set(topOffset);
			}
		}

		protected void RotateStairs(Stairs stairs, XYZ ptInsert)
		{
			Transaction transaction = new Transaction(this.m_Document, "rotate stairs");
			transaction.Start();
			double viewRotateAngle = ViewUtils.GetViewRotateAngle(this.m_Document.ActiveView);
			YJKRevitStairs.StairsModel.CommonUnit.Geometry.TransformElemnetAtPoint(this.m_Document, ptInsert, stairs.Id, viewRotateAngle);
			transaction.Commit();
		}

		private ExternalCommandData m_Revit;

		protected Document m_Document;

		protected string m_RevitVersion = "";
	}
}
